import { styled, Access } from '@umijs/max'
import { PlusOutlined } from "@ant-design/icons"
import { Image, message } from 'antd'
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  rectSortingStrategy,
} from "@dnd-kit/sortable";
import ImageItem from './ImageItem';
import { fileUp } from '@/services/common';

const Container = styled.div`
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 12px;
`

type Value = {
  id: string
  type: 'Image' | 'Video'
  source: string
}

interface ImageGroupProps {
  value?: Value[]
  onChange?: (value?: Value[]) => void
  style?: React.CSSProperties
  className?: string
  max?: number
  tips?: string[]
  accept?: string
  sortable?: boolean
}

export const ImageGroupValidator = (msg: string, value?: Value[]) => {
  if (!value?.length) {
    return Promise.reject(new Error(msg))
  }
  return Promise.resolve()
}

const ImageGroup: React.FC<ImageGroupProps> = props => {
  const del = (source: string) => {
    props.onChange?.(props.value?.filter(it => it.source !== source))
  }

  const onChange = (e: {target: {files: any[]}}) => {
    const { files } = e.target
    let error = false
    for (const file of files) {
      if (file.size > 1024 * 1023 * 2) {
        error = true
        message.error('请选择小于2M的图片')
        break
      }
    }
    if (error) return
    const _loading = message.loading('上传中', 0)
    const _promiseList = []
    for (const file of files) {
      const _formData = new FormData()
      _formData.append('type', '2')
      _formData.append('file', file)
      _promiseList.push(fileUp(_formData))
    }
    Promise.all(_promiseList).then(res => {
      const _value: Value[] = [...(props.value || [])]
      const _count = Math.min((props.max || 10000) - _value.length, files.length)
      for (let i=0; i<_count; i++) {
        const _url = res[i].data
        _value.push({
          id: _url,
          type: files[i].type.startsWith('image') ? 'Image' : 'Video',
          source: _url,
        })
      }
      props.onChange?.(_value)
    }).finally(() => {
      _loading()
    })
  }

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates
    })
  );

  const handleDragEnd = (event: any) => {
    const { active, over } = event;

    if (active.id !== over.id) {
      const oldIndex = props.value!.findIndex(it => it.id === active.id);
      const newIndex = props.value!.findIndex(it => it.id === over.id);

      props.onChange?.(arrayMove(props.value!, oldIndex, newIndex));
    }
  }

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <Container className={props.className} style={props.style}>
        {
          props.sortable === false ? <Image.PreviewGroup>
            {
              props.value?.map(it => {
                return <ImageItem key={it.source} value={it} onDel={del} sortable={props.sortable}></ImageItem>
              })
            }
          </Image.PreviewGroup> : <SortableContext items={props.value || []} strategy={rectSortingStrategy}>
            <Image.PreviewGroup>
              {
                props.value?.map(it => {
                  return <ImageItem key={it.source} value={it} onDel={del} sortable={props.sortable}></ImageItem>
                })
              }
            </Image.PreviewGroup>
          </SortableContext>
        }
        <Access accessible={(props.value?.length || 0) < (props.max || 10000)}>
          <div className="w-24 h-24 rounded-xl border-dashed border flex items-center justify-center relative">
            <PlusOutlined className='text-2xl' />
            <input className="absolute inset-0 opacity-0 cursor-pointer" type="file" multiple={(props.max || 10000) > 1 ? true : false} accept={props.accept || 'image/jpg, image/png'} onChange={onChange} />
          </div>
        </Access>
      </Container>
      {
        props.tips?.map((tip, index) => {
          return <div key={index} style={{marginTop: 8, color: '#ff4040'}}>* {tip}</div>
        })
      }
    </DndContext>
  )
}

export default ImageGroup